<?php

namespace app\devices\controller\api;

use app\data\service\ALiMsgService;
use app\devices\service\BoxService;
use app\devices\service\DevicesService;
use app\devices\service\SocketService;
use app\devices\service\VipService;
use Cassandra\Date;
use think\admin\Service;
use think\App;
use think\cache\driver\Redis;
use think\facade\Log;

/**
 * 设备数据接口
 * Class Index
 * @package app\data\controller\api
 */
class Index extends Auth
{
    protected $redis;

    public function __construct(App $app)
    {
        parent::__construct($app);
        $this->redis = new Redis();
    }

    public function getStore(){
        $data = $this->_vali(
            [
                'distance.default' => '',
            ]
        );

        $query = $this->_query('jcg_store');
        $result = $query->where('status', 1)->field("id as store_id, name, store_img, address, area, points")->order('id desc')->page(true, false, false, 10);

        DevicesService::instance()->buildStoreData($result['list'], $data['distance']);

        $this->success('获取柜点成功', $result);
    }

    /**
     * 获取设备数据
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getDevices()
    {
        $data = $this->_vali(
            [
                'store_id.require' => '柜点id不能为空',
            ]
        );

        $query = $this->_query('JcgDevices');
        $result = $query->where(['online'=>1, 'store_id'=>$data['store_id']])->field("id as d_id, device_name, image")->order('id desc')->page(true, false, false, 10);

        DevicesService::instance()->buildItemData($result['list']);

        $this->success('获取设备成功', $result);
    }


    /**
     * 设置取件码
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function setPickUpCode(){
        $data = $this->_vali(
            [
                'd_id.require' => '设备ID不可为空！',
                'code.require' => '取件码不能为空',
                'user_id' => $this->uuid,
                'mobile.default' => $this->user['phone'],
            ]
        );

        $res = DevicesService::instance()->setPickUpCode($data);
        if($res){
            $this->success("设置成功");
        }else{
            $this->error("设置失败");
        }
    }

    /**
     * 获取箱门数据
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getBox(){
        $data = $this->_vali(
            [
                'd_id.require' => '设备ID不可为空！',
                'box_id.default'=>'',
                'box_num.default' => '',
            ]
        );
        $userTjBox = $this->redis->get("userTjBox".$this->uuid);
        if($userTjBox){
            $tjBoxUid = $this->redis->get("TjBox".$userTjBox);
            if($this->uuid!=$tjBoxUid && $userTjBox){
                $this->error("箱格已被使用:".$tjBoxUid);
            }
            $this->redis->delete("TjBox".$userTjBox);
            unset($userTjBox, $uuid);
        }

        if($data['box_id']){
            $tjBoxUid = $this->redis->get("TjBox".$data['box_id']);
            if($this->uuid!=$tjBoxUid && $tjBoxUid){
                $this->error("箱格已被使用");
            }
        }
        $box_id = $data['box_id']?$data['box_id']:BoxService::instance()->getBoxId($data['d_id']);
        $this->redis->set("TjBox".$box_id, $this->uuid,120);
        $this->redis->set("userTjBox".$this->uuid, $box_id,120);


        $deviceService = DevicesService::instance();

        $device = $deviceService->getDevice($data['d_id']);
        if(empty($device)){
            $this->error("设备不存在");
        }

        $max_open = sysconf('contact.max_open');
        $use_box = $this->redis->handler()->ZRANGEBYSCORE('orderUseBox'.$data['d_id'], $this->uuid, $this->uuid);
        if($max_open && count($use_box)>=$max_open){
            $this->error("您已使用了".$max_open."个柜子");
        }

        $store = DevicesService::instance()->getStore($device['store_id']);

        if($store['bus_hours']<1){
            $end = explode(":", $store['end_hours']);
            $start = explode(":", $store['start_hours']);

            if(date("Hi")<(int)($start[0].$start[1]) || date("Hi")>(int)($end[0].$end[1])){
                $this->error('当前不在营业时间',[],2);
            }
        }

        if($data['box_num']){
            $box = BoxService::instance()->getBox(0, ['d_id'=>$data['d_id'], 'box_num'=>$data['box_num']]);
            if(!empty($box)){
                $this->error('箱柜不存在');
            }
        }else if($box_id){
            $box = BoxService::instance()->getBox($box_id);
            if(empty($box)){
                $this->error('箱柜不存在');
            }
        }else{
            $device_no = BoxService::instance()->getNearNotFallDeviceNo($device['store_id'], $data['d_id']);
            $this->success('箱柜已满',['is_full'=>1, 'device_no'=>$device_no]);
        }

        $boxs[] = $box;

        BoxService::instance()->buildData($boxs, $device['fee_id']);

        $result['store'] = [
            'business_hours'=>$store['bus_hours']?'全天':(substr($store['start_hours'],0,5).' - '.substr($store['end_hours'],0,5)),
            'name'=>$device['device_name']
        ];

        $rank = $this->redis->handler()->ZRANK("UserDiscounts", $this->uuid);
        if(is_numeric($rank)){
            $discounts = $this->redis->handler()->Zscore("UserDiscounts", $this->uuid);
            if($discounts>0){
                $boxs[0]['discounts'] = $discounts;
                $boxs[0]['m_fee_price'] = $boxs[0]['fee_price'];
                $boxs[0]['fee_price'] = $boxs[0]['fee_price']?sprintf("%.2f", $boxs[0]['fee_price']*($discounts/100)):0;
                $boxs[0]['price'] = $boxs[0]['price']?sprintf("%.2f", $boxs[0]['price']*($discounts/100)):0;
            }else{
                $boxs[0]['fee_price'] = $boxs[0]['price'] = 0;
            }
        }

        $vip = VipService::instance()->getUserVip($this->uuid);
        if($vip){
            $boxs[0]['fee_price'] = $boxs[0]['price'] = 0;
        }

        $result['box'] = $boxs[0];
        $result['is_full'] = 0;
        $result['is_optional'] = $device['is_optional']??2;

        $this->success("获取箱门数据成功", $result);
    }

    /**
     * 获取箱门列表数据
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getBoxs(){
        $data = $this->_vali(
            [
                'd_id.require' => '设备ID不可为空！',
            ]
        );

        $query = $this->_query('JcgBoxs')->equal("d_id");

        $list = $query->field("id as box_id, d_id, box_num, box_type, is_lock, box_status, user_type")->order('box_num asc')->page(false, false);

        $device = DevicesService::instance()->getDevice($data['d_id']);
        if(empty($device)){
            $this->error("设备不存在");
        }

        $store = DevicesService::instance()->getStore($device['store_id']);

        BoxService::instance()->buildData($list['list'], $device['fee_id']);

        $result['store'] = [
            'business_hours'=>$store['bus_hours']?'全天':(substr($store['start_hours'],0,5).' - '.substr($store['end_hours'],0,5)),
            'name'=>$device['device_name']
        ];
        $result['list'] = $list['list'];

        $this->success("获取箱门数据成功", $result);
    }

    /**
     * 获取联系我们和常见问题富文本
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getContact(){
        $config = sysconf();
        $contact = $config['contact'];

        $contact['problem'] = $this->app->db->name('DataNewsItem')->where("mark", "like",",常见问题,")->value("content");

        $service = sysdata('agreement');

        $contact['business_logo'] = $config['edition']['business_logo'];
        $contact['version'] = $config['edition']['versionName'];

        $contact['service'] = $service['content'];

        $this->success('成功', $contact);
    }

    /**
     * 意见反馈
     */
    public function feedBack(){
        $redis = new Redis();
        $data = $this->_vali(
            [
                'contents.default' => '',
                'images.default' => ''
            ]
        );
        if($redis->get("feedBack".$this->uuid)){
            $this->error("点击过快");
        }

        if(empty($data['contents']) && empty($data['images'])){
            $this->error("反馈内容不能为空");
        }
        $data['user_id'] = $this->uuid;
        $res =  $this->app->db->name("jcg_feedback")->insert($data);
        if($res){
            $redis->set("feedBack".$this->uuid, 1,5);
            $this->success("成功");
        }else{
            $this->error('失败');
        }
    }

    /**
     * 发送短信验证码
     */
    public function sendSms(){
        $data = $this->_vali(
            [
                'phone.require'=>'手机号不能为空',
            ]
        );

        $wait = 300;

        $cache = $this->app->cache->get($ckey = md5("code-{$data['phone']}"), []);
        // 检查是否已经发送
        if (is_array($cache) && isset($cache['time']) && $cache['time'] > time() - $wait) {
            $this->success("短信验证码5分钟内有效");
        }
        // 生成新的验证码
        [$code, $time] = [rand(100000, 999999), time()];
        $this->app->cache->set($ckey, ['code' => $code, 'time' => $time], $wait);

        $res = ALiMsgService::sendSms($data['phone'], $code);
        if($res){
            $this->success("验证码发送成功");
        }else{
            $this->error("验证码发送失败");
        }
    }

    /**
     * 绑定手机号
     * @throws \think\db\exception\DbException
     */
    public function bindPhone(){
        $data = $this->_vali(
            [
                'phone.require'=>'手机号不能为空',
                'code.default'=>'',
                'store_id.default'=>0,
            ]
        );

        $is_msg = 0;
//        if($data['store_id']){
//            $store = DevicesService::instance()->getStore($data['store_id']);
//            $is_msg = $store['is_msg'];
//        }
        if($is_msg && $data['code']){
            if(isset($data['code']) && $data['code']){
                $wait = 300;
                $cache = $this->app->cache->get($ckey = md5("code-{$data['phone']}"), []);
                if (is_array($cache) && isset($cache['time']) && $cache['time'] < time() - $wait) {
                    $this->success("验证码已失效");
                }else if(empty($cache)){
                    $this->error("验证码已失效");
                }else if($cache['code']!=$data['code']){
                    $this->error("验证码有误");
                }
            }else{
                $this->error("验证码不能为空");
            }
        }

        if($this->user['phone']==$data['phone']){
            $this->success("手机号未发生改变");
        }
        $res = $this->app->db->name("data_user")->where("id", $this->uuid)->update(["phone"=>$data['phone']]);
        if($res){
            $this->success("成功");
        }else{
            $this->error('失败');
        }
    }

    /**
     * 获取用户数据
     * @return array
     */
    public function getUserInfo(): array
    {
        $user = $this->user;
        unset($user['openid1'], $user['openid2'], $user['unionid']);
        $this->success('成功', $user);
    }

    /**
     * 获取会员信息
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getVipInfo(): array
    {

        $list = $this->app->db->name('JcgVipLevel')->field("id, name, amount, summary, days")->order('sort desc,id desc')->select()->toArray();

        $vip = VipService::instance()->getUserVip($this->uuid);

        $end_day = ceil((($vip['end_time']??0)-time())/86400);

        $this->success("获取会员信息成功", ['vip_end_time'=>$end_day>0?$end_day:0, 'list'=>$list]);
    }

    /**
     * 发送获取设备箱格数量的命令
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getBoxSocket(){
        $data = $this->_vali(
            [
                'device_id.require'=>'设备ID不能为空',
            ]
        );
        $device_id = $data['device_id'];
        if($device_id){
//            $socket = new SocketService($this->app);

//            $device = DevicesService::instance()->getDevice(0, $device_id);

//            $boards = $this->app->db->name("jcg_boxs")->where("d_id", $device['id'])->group("device_board")->column("device_board");
//            foreach ($boards as $row){
//                $msg = ['type'=>1, 'device_id'=>$device_id, 'device_board'=>$row, 'is_auto'=>1];
//                $socket->sendSocket($msg, 1);
//            }
            $this->success("指令已发送");
        }
    }

    public function autoSend()
    {
        set_time_limit(0);
        ignore_user_abort(true);//设置与客户机断开是否会终止执行
        fastcgi_finish_request();//提高请求的处理速度
        $data = $this->_vali(
            [
                'device_id.require'=>'设备ID不能为空',
            ]
        );
        $device_id = $data['device_id'];
        try {
            $send = 1;
            $s=1;
            $info = '';
            while ($send){
                $send = $this->redis->handler()->lpop("LockSocket".$device_id);
                if($send){
                    $s++;
                    $send = json_decode($send, true);
                    $send['is_send'] = 1;
                    $send['send_time'] = date("Y-m-d H:i:s");
                    SocketService::instance()->sendSocket($send, 1);

                    if($send['type']==2){
                        $key = $device_id.'_'.$send['device_board'].'_'.$send['ch'];
                        $t1=microtime(true);
                        $flag = true;
                        while (!$this->redis->get("OpenCmd".$key)){
                            $t2=microtime(true);
                            if($t2-$t1>=1.8){
                                $flag = false;
                                break;
                            }
                            $send['openTime'] = round($t2-$t1,2);
                            usleep(600000);
                        }
                        if(!$flag){
                            SocketService::instance()->sendSocket($send, 1);
                            while (!$this->redis->get("OpenCmd".$key)){
                                $t2=microtime(true);
                                if($t2-$t1>=1.8){
                                    break;
                                }
                                $send['openTime'] = round($t2-$t1,2);
                                usleep(600000);
                            }
                        }
                    }else{
                        sleep(1);
                    }
                    $info .= json_encode($send, 256).PHP_EOL;
                }else{
                    break;
                }
            }
            print_r($info);
            if(empty($this->redis->handler()->llen("LockSocket".$device_id))){
                $this->redis->delete("AUTO_".$device_id);
            }
            $this->redis->set("Died_".$device_id,1,1);
            exit(0);
        } catch (\Exception $exception) {
            Log::error($exception->getMessage()."_".$exception->getLine());
            $this->redis->delete("AUTO_".$device_id);
            exit(0);
        }
    }

    public function flush(){
        set_time_limit(0);
        ignore_user_abort(true);//设置与客户机断开是否会终止执行
        fastcgi_finish_request();//提高请求的处理速度
        $device_id = input("device_id");
        if($device_id){
            $device = DevicesService::instance()->getDevice(0,$device_id);
            $d_id = $device['id'];
            $socket = new SocketService($this->app);

            $map['d_id'] = $d_id;
            $map['is_lock'] = 2;

            $boards = $this->app->db->name("jcg_boxs")->where($map)->group("device_board")->column("device_board");
            foreach ($boards as $row){
                $msg = ['type'=>1, 'device_id'=>$device['device_id'], 'device_board'=>$row];
                $socket->sendSocket($msg, 1);
                $res = $this->redis->get("BoardStatus".$device['device_id'].$row);
                $s = 1;
                while (!$res){
                    $res = $this->redis->get("BoardStatus".$device['device_id'].$row);
                    if($res || $s>3){
                        break;
                    }
                    usleep(600000);
                    $s++;
                }
            }
        }
        $this->success("指令已发送");
    }
}